package com.lin.filegraph.utils.calculator;

import com.lin.filegraph.utils.parser.node.*;
import com.lin.filegraph.utils.parser.simpleast.SimpleASTHelper;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 10:11
 */
public class CodeSizeCalculator {

    public static int calculateSizeOfNode(JTreeNode node) {
        if (node.getStartLine() >= 0 && node.getEndLine() >= 0) {
            return node.getEndLine() - node.getStartLine() + 1;
        } else {
            if (node instanceof JProjectNode || node instanceof JPackageNode || node instanceof JDirectoryNode) {
                int size = 0;
                List<JFileNode> listFileNode = SimpleASTHelper.findAllFilesInSubTree(node);
                for (JFileNode fileNode : listFileNode) {
                    size += fileNode.getEndLine() - fileNode.getStartLine() + 1;
                }
                return size;
            }
        }
        return -1;
    }

    public static int calculateValidSizeOfNode(JTreeNode node) {
        if (node instanceof JFileNode) {
            return ((JFileNode) node).getValidLOC();
        } else {
            if (node instanceof JProjectNode || node instanceof JPackageNode || node instanceof JDirectoryNode) {
                int validSize = 0;
                List<JFileNode> listFileNode = SimpleASTHelper.findAllFilesInSubTree(node);
                for (JFileNode fileNode : listFileNode) {
                    validSize += fileNode.getValidLOC();
                }
                return validSize;
            }
        }
        return -1;
    }

    public static int calculateValidSizeOfAST(CompilationUnit ast) {
        String code = ast.toString();
        List<String> strLines = splitCode(code);
        int allLines = strLines.size();
        int javadocLines = 0;

        for (String strLine : strLines) {
            strLine = strLine.trim();
            if (strLine.startsWith("/*") || strLine.startsWith("*") || strLine.endsWith("*/")) {
                javadocLines++;
            }
        }

        int validLine = allLines - javadocLines;
//		System.out.println("LOC:"+ calculateLOC(ast));
//		System.out.println("allLines:"+ allLines);
//		System.out.println("javadocLines:"+ javadocLines);
//		System.out.println("validLine:"+ validLine);
        return validLine;
    }

    private static List<String> splitCode(String code) {
        List<String> lines = new ArrayList<>();
        BufferedReader br = new BufferedReader(new StringReader(code));
        String line = "";
        try {
            while ((line = br.readLine()) != null) {
                lines.add(line);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return lines;
    }

    public static int calculateStartLine(ASTNode astNode) {
        if (astNode != null) {
            CompilationUnit compilationUnit = (CompilationUnit) astNode.getRoot();
            return compilationUnit.lineNumber(astNode.getStartPosition());
        } else {
            return -1;
        }
    }

    public static int calculateEndLine(ASTNode astNode) {
        if (astNode != null) {
            CompilationUnit compilationUnit = (CompilationUnit) astNode.getRoot();
            return compilationUnit.lineNumber(astNode.getStartPosition() + astNode.getLength() - 1);
        } else {
            return -1;
        }
    }

    public static int calculateLOC(ASTNode astNode) {
        return calculateEndLine(astNode) - calculateStartLine(astNode) + 1;
    }
}
